package com.Tread;

import java.util.LinkedList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 要注意,catch时，要signal
 */
 class ConcurrentQueue {

    private volatile int size;

    private int capacity = 5;

    LinkedList<Integer> queue = new LinkedList<>();

    ReentrantLock lock = new ReentrantLock();

    Condition full = lock.newCondition();

    Condition empty = lock.newCondition();



    public Integer take() {

        try {
            lock.lock();
            while (queue.size() == 0) {
                empty.await();
            }
            Integer result = queue.removeFirst();
            full.signal();
            return result;
        } catch (Exception exception) {
            empty.signal();
            exception.printStackTrace();
        } finally {
            lock.unlock();
        }
        return 0;
    }

    public void put(Integer val) {
        try {
            try {
                lock.lock();
                while (queue.size() == this.capacity) {
                    full.await();
                }
            } catch (Exception exception) {
                full.signal();
                exception.printStackTrace();
            }
            queue.offerLast(val);
            empty.signal();
        }
        finally {
            lock.unlock();
        }
    }

}

public class ConcurrentQueueTest {
    public static void main(String[] args) {
        ConcurrentQueue queue = new ConcurrentQueue();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                queue.put(i);
                System.out.println("塞入" + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(() -> {
            for (; ; ) {
                System.out.println("消费"+queue.take());
                try {
                    Thread.sleep(800);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        t2.start();
    }
}
